#pragma once
#include <stdio.h>
#include <stdint.h>

// bn big_number大数， 即uint256
// bbn big_big_number大数， 即uint512
//大数
typedef uint64_t sm2_bn_type[4];
typedef uint64_t sm2_bbn_type[8];

void sm2_bn_set_zero(sm2_bn_type r);

int sm2_bn_rand_range(sm2_bn_type r, const sm2_bn_type range);

void sm2_bn_copy(sm2_bn_type d, const sm2_bn_type s);

void sm2_bn_copy_conditional(sm2_bn_type dst, const sm2_bn_type src, uint64_t move);

void sm2_bn_from_bytes(sm2_bn_type r, const uint8_t in[32]);

void sm2_bn_to_bytes(const sm2_bn_type a, uint8_t out[32]);

int sm2_bn_compare(const sm2_bn_type a, const sm2_bn_type b);

uint64_t sm2_bn_is_zero(const sm2_bn_type a);

uint64_t sm2_bn_is_equal(const sm2_bn_type a, const sm2_bn_type b);

uint64_t sm2_bn_plus(sm2_bn_type result, const sm2_bn_type a, const sm2_bn_type b);

uint64_t sm2_bn_subtraction(sm2_bn_type result, const sm2_bn_type a, const sm2_bn_type b);

void sm2_bn_multiplication(sm2_bbn_type result, const sm2_bn_type a, const sm2_bn_type b);

int sm2_bn_get_booth(const sm2_bn_type a, unsigned int window_size, int unsigned i);

void sm2_bn_from_hex(sm2_bn_type r, const char *hex);

int sm2_bn_printf(const char *label, const sm2_bn_type a);

void sm2_bn_mod_p_plus(sm2_bn_type r, const sm2_bn_type a, const sm2_bn_type b);

void sm2_bn_mod_p_double(sm2_bn_type r, const sm2_bn_type a);

void sm2_bn_mod_p_triple(sm2_bn_type r, const sm2_bn_type a);

void sm2_bn_mod_p_subtraction(sm2_bn_type r, const sm2_bn_type a, const sm2_bn_type b);

void sm2_bn_mod_p_negative(sm2_bn_type r, const sm2_bn_type a);

void sm2_bn_mod_p_half(sm2_bn_type r, const sm2_bn_type a);

void sm2_bn_mod_p_to_mont(const sm2_bn_type a, sm2_bn_type r);

void sm2_bn_mod_p_from_mont(sm2_bn_type r, const sm2_bn_type a);

void sm2_bn_mod_p_mont_multiplication(sm2_bn_type r, const sm2_bn_type a, const sm2_bn_type b);

void sm2_bn_mod_p_mont_sqr(sm2_bn_type r, const sm2_bn_type a);

void sm2_bn_mod_p_mont_exp(sm2_bn_type r, const sm2_bn_type a, const sm2_bn_type e);

void sm2_bn_mod_p_mont_inv(sm2_bn_type r, const sm2_bn_type a);

void sm2_bn_mod_n_plus(sm2_bn_type r, const sm2_bn_type a, const sm2_bn_type b);

void sm2_bn_mod_n_subtraction(sm2_bn_type r, const sm2_bn_type a, const sm2_bn_type b);

void sm2_bn_mod_n_inv(sm2_bn_type r, const sm2_bn_type a);

void sm2_bn_mod_n_to_mont(const sm2_bn_type a, sm2_bn_type r);

void sm2_bn_mod_n_from_mont(sm2_bn_type r, const sm2_bn_type a);

void sm2_bn_mod_n_mont_multiplication(sm2_bn_type r, const sm2_bn_type a, const sm2_bn_type b);

void sm2_bn_mod_n_mont_sqr(sm2_bn_type r, const sm2_bn_type a);

void sm2_bn_mod_n_mont_inv(sm2_bn_type r, const sm2_bn_type a);

//椭圆曲线定义
typedef struct {
    sm2_bn_type X;
    sm2_bn_type Y;
    sm2_bn_type Z;
} sm2_bn_point_type;

void sm2_bn_point_set_infinity(sm2_bn_point_type *P);

int sm2_bn_point_is_at_infinity(const sm2_bn_point_type *P);

int sm2_bn_point_to_bytes(const sm2_bn_point_type *P, uint8_t out[64]);

int sm2_bn_point_from_bytes(sm2_bn_point_type *P, const uint8_t in[64]);

int sm2_bn_point_from_hex(sm2_bn_point_type *P, const char *hex);

int sm2_bn_point_is_on_curve(const sm2_bn_point_type *P);

int sm2_bn_point_get_xy(const sm2_bn_point_type *P, uint64_t x[4], uint64_t y[4]);

void sm2_bn_point_double(sm2_bn_point_type *R, const sm2_bn_point_type *A);

void sm2_bn_point_plus(sm2_bn_point_type *r, const sm2_bn_point_type *a, const sm2_bn_point_type *b);

void sm2_bn_point_negative(sm2_bn_point_type *R, const sm2_bn_point_type *P);

void sm2_bn_point_subtraction(sm2_bn_point_type *R, const sm2_bn_point_type *A, const sm2_bn_point_type *B);

int sm2_bn_point_printf(const char *label, const sm2_bn_point_type *P);

//仿射点定义
typedef struct {
    sm2_bn_type x;
    sm2_bn_type y;
} SM2_BN_AFFINE_POINT;

void sm2_bn_point_copy_affine(sm2_bn_point_type *R, const SM2_BN_AFFINE_POINT *P);

void sm2_bn_point_add_affine(sm2_bn_point_type *r, const sm2_bn_point_type *a, const SM2_BN_AFFINE_POINT *b);

void sm2_bn_point_sub_affine(sm2_bn_point_type *R, const sm2_bn_point_type *A, const SM2_BN_AFFINE_POINT *B);

void sm2_bn_point_mul_generator(sm2_bn_point_type *R, const sm2_bn_type k);

void sm2_bn_point_mul_pre_compute(const sm2_bn_point_type *P, sm2_bn_point_type T[16]);

void sm2_bn_point_mul_ex(sm2_bn_point_type *R, const sm2_bn_type k, const sm2_bn_point_type P_table[16]);

//大数取值
const uint64_t *sm2_bn_prime(void);

const uint64_t *sm2_bn_order(void);

const uint64_t *sm2_bn_order_minus_one(void);

const uint64_t *sm2_bn_one(void);
